package com.randb.easyhttp.utils;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Looper;

import com.randb.easyhttp.callback.Callback;

import java.io.Closeable;
import java.io.IOException;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import okhttp3.RequestBody;

/**
 * User: RandBII
 * Date: 2020/5/8
 * Description:
 */
public class Utils {

    public static <T> T checkNotNull(T t, String message) {
        if (t == null) {
            throw new NullPointerException(message);
        } else {
            return t;
        }
    }


    public static boolean checkMain() {

        return Thread.currentThread() == Looper.getMainLooper().getThread();
    }

    public static Type findNeedClass(Class<? extends Callback> aClass) {

        Type genericType = aClass.getGenericSuperclass();
        Type params[] = ((ParameterizedType) genericType).getActualTypeArguments();
        Type type = params[0];
        Type finalNeedType;
        if (params.length > 1) {
            if (!(type instanceof ParameterizedType)) throw new IllegalArgumentException("未填写泛型类型");
            finalNeedType = ((ParameterizedType) type).getActualTypeArguments()[0];
        } else {
            finalNeedType = type;
        }
        return finalNeedType;
    }

    public static <T> Type findRawType(Class<T> aClass) {

        Type type = aClass.getGenericSuperclass();
        return getGenericType((ParameterizedType) type, 0);

    }


    public static <T> List<Type> getMethodTypes(Class<T> cls) {

        Type typeOri = cls.getGenericSuperclass();
        List<Type> needTypes = null;
        if (typeOri instanceof ParameterizedType) { // typeOri 是个泛型
            needTypes = new ArrayList<>();
            Type[] parentTypes = ((ParameterizedType) typeOri).getActualTypeArguments();
            for (Type childType : parentTypes) {
                needTypes.add(childType);
                if (childType instanceof ParameterizedType) {
                    Type[] childTypes = ((ParameterizedType) childType).getActualTypeArguments();
                    Collections.addAll(needTypes, childTypes);
                }
            }

        }
        return needTypes;
    }


    public static Type getType(Type type, int i) {

        if (type instanceof ParameterizedType) {
            return getGenericType((ParameterizedType) type, i);
        } else if (type instanceof TypeVariable) {
            return getType(((TypeVariable) type).getBounds()[0], 0);
        } else {
            return type;
        }


    }

    private static Type getGenericType(ParameterizedType type, int i) {
        Type genericType = type.getActualTypeArguments()[i];
        if (genericType instanceof ParameterizedType) { // 处理多级泛型
            return ((ParameterizedType) genericType).getRawType();
        } else if (genericType instanceof GenericArrayType) {
            return ((GenericArrayType) genericType).getGenericComponentType();
        } else if (genericType instanceof TypeVariable) {
            return getClass(((TypeVariable) genericType).getBounds()[0], 0);
        } else {
            return genericType;
        }

    }

    public static Class getClass(Type type, int i) {
        if (type instanceof ParameterizedType) {
            return getGenericClass((ParameterizedType) type, i);
        } else if (type instanceof TypeVariable) {
            return getClass(((TypeVariable) type).getBounds()[0], 0);
        } else {
            return (Class) type;
        }
    }


    private static Class getGenericClass(ParameterizedType type, int i) {

        Type genericClass = type.getActualTypeArguments()[i];
        if (genericClass instanceof ParameterizedType) { // 泛型
            return (Class) ((ParameterizedType) genericClass).getRawType();
        } else if (genericClass instanceof GenericArrayType) {  // 泛型数组
            return (Class) ((GenericArrayType) genericClass).getGenericComponentType();
        } else if (genericClass instanceof TypeVariable) { // 泛型擦除
            return getClass(((TypeVariable) genericClass).getBounds()[0], 0);
        } else {
            return (Class) genericClass;
        }

    }

    public static boolean getNetWorkAvailable(Context context) {

        ConnectivityManager manager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (manager == null) return false;
        NetworkInfo info = manager.getActiveNetworkInfo();
        return info != null && info.isAvailable();

    }

    public static Type getParameterizedType(Type type, int i) {

        if (type instanceof ParameterizedType) { // 处理泛型类型
            Type genericType = ((ParameterizedType) type).getActualTypeArguments()[i];
            return genericType;
        } else if (type instanceof TypeVariable) {
            return getType(((TypeVariable) type).getBounds()[0], 0); // 处理泛型擦拭对象
        } else {// class本身也是type，强制转型
            return type;
        }
    }


    public static <R> Type findNeedType(Class<R> aClass) {
        List<Type> typeList = Utils.getMethodTypes(aClass);
        if (typeList == null || typeList.isEmpty()) {
            return RequestBody.class;
        }
        return typeList.get(0);
    }


    public static void close(Closeable close) {
        if (close != null) {
            try {
                closeThrowException(close);
            } catch (IOException ignored) {
            }
        }
    }

    public static void closeThrowException(Closeable close) throws IOException {
        if (close != null) {
            close.close();
        }
    }
}
